package cn.bitkit.tools.file;

import java.io.File;
import java.io.FileInputStream;
import java.security.MessageDigest;
import java.util.zip.CRC32;

import cn.bitkit.base.util.StringUtil;
import lombok.Cleanup;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.crypto.digests.SM3Digest;

@Slf4j
public class HashUtil {
	
	private static final String MD5 = "MD5";
	private static final String SHA1 = "SHA-1";
	private static final String SHA256 = "SHA-256";
	private static final String SHA512 = "SHA-512";
	private static final String ENCODING = "UTF-8";

	public static String getMD5(String text){
		return getHash(text, MD5);
	}
	public static String getMD5(File file){
		return getHash(file, MD5);
	}
	public static String getSHA1(String text){
		return getHash(text, SHA1);
	}
	public static String getSHA1(File file){
		return getHash(file, SHA1);
	}
	public static String getSHA256(String text){
		return getHash(text, SHA256);
	}
	public static String getSHA256(File file){
		return getHash(file, SHA256);
	}
	public static String getSHA512(String text){
		return getHash(text, SHA512);
	}
	public static String getSHA512(File file){
		return getHash(file, SHA512);
	}

	@SneakyThrows
	private static String getHash(String text, String sha){
		if(text == null){
			return null;
		}
		MessageDigest md = MessageDigest.getInstance(sha);
		md.update(text.getBytes(ENCODING));
		byte[] b = md.digest();
		return StringUtil.bytesToHexStr(b);
	}

	@SneakyThrows
	private static String getHash(File file, String sha){
		if(file == null || !file.exists()){
			return null;
		}
		MessageDigest md = MessageDigest.getInstance(sha);
		@Cleanup
		FileInputStream fis = new FileInputStream(file);
		byte[] buffer = new byte[8192];
		int length;
		while ((length = fis.read(buffer)) != -1) {
			md.update(buffer, 0, length);
		}
		byte[] b = md.digest();
		return StringUtil.bytesToHexStr(b);
	}

	public static long getCRC32(String text){
		if(text == null){
			return 0;
		}
		CRC32 crc32 = new CRC32();
		crc32.update(text.getBytes());
		return crc32.getValue();
	}

	@SneakyThrows
	public static long getCRC32(File file) {
		if(file == null){
			return 0;
		}
	    CRC32 crc32 = new CRC32();
		@Cleanup
	    FileInputStream fis = new FileInputStream(file);
		byte[] buffer = new byte[8192];
		int length;
		while ((length = fis.read(buffer)) != -1) {
			crc32.update(buffer,0, length);
		}
		return crc32.getValue();
	}
	public static String getSM3(String text){
		if(text == null){
			return null;
		}
		SM3Digest digest = new SM3Digest();
		byte[] data = text.getBytes();
		digest.update(data, 0, data.length);
		byte[] result = new byte[digest.getDigestSize()];
		digest.doFinal(result, 0);
        return StringUtil.bytesToHexStr(result);
	}

	@SneakyThrows
	public static String getSM3(File file){
		if(file == null){
			return null;
		}
		SM3Digest digest = new SM3Digest();
		@Cleanup
		FileInputStream fis = new FileInputStream(file);
		byte[] buffer = new byte[8192];
		int length;
		while ((length = fis.read(buffer)) != -1) {
			digest.update(buffer, 0, length);
		}
		byte[] result = new byte[digest.getDigestSize()];
		digest.doFinal(result, 0);
		return StringUtil.bytesToHexStr(result);
	}
	
}
